package com.essence.grabiec104.grab.executor.handler;

import com.essence.common.model.BytesFrame;
import com.essence.common.model.Packet;
import com.essence.common.model.Point;
import com.essence.common.model.Substation;
import com.essence.common.model.parser.PacketVerifyException;
import com.essence.grabiec104.grab.dao.AlarmDao;
import com.essence.grabiec104.grab.dao.GrabberDao;
import com.essence.grabiec104.grab.service.AlarmService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @brief 消息发布者
 * @details 消息发布者，将消息发布到消息队列中，供其他服务订阅，使用ZeroMQ:Dealer-Router模式
 */
@Component
@Slf4j
public class AnalysisHandler extends AbstractSocketFrameHandler {
    @Autowired
    private AlarmDao alarmDao;
    @Autowired
    private GrabberDao grabberDao;
    @Autowired
    private AlarmService alarmService;
    @Override
    protected boolean doHandle(BytesFrame frame) {
        try {
            return addPacket(frame);
        } catch (Exception ex) {
            log.error("publish error", ex);
        }
        return false;
    }

    @Override
    public String getName() {
        return "AnalysisHandler";
    }


    @Transactional
    public boolean addPacket(BytesFrame frame) {
        try {
            String host = "";
            int port = 0;
            int direction = 0;
            if (frame.getDirection() == BytesFrame.DirectionEnum.Upstream) {
                host = frame.getSrcHost();
                direction = 0;
                port = frame.getSrcPort();
            }
            if (frame.getDirection() == BytesFrame.DirectionEnum.Downstream) {
                host = frame.getDstHost();
                direction = 1;
                port = frame.getDstPort();
            }
            // 确保当前报文属于已注册的子站
            Substation substation = null;
            List<Substation> allSubstation = alarmService.getAllSubstation();
            for (Substation si : allSubstation) {
                if (si.getHost().equals(host) && si.isRtu()) {
                    // 更新子站扫描标识
                    log.info("子站{}, 将扫描标识置为0", host);
                    alarmDao.updateStationInfoScanFlag(host, 0);
                    substation = si;
                }
            }

            if (substation == null) {
                log.error("子站{}未注册", host);
                return false;
            }

            // 向数据库插入原始报文信息
            frame.setSubstationId(substation.getId());
            grabberDao.insertBytesFrame(frame);

            // 根据IEC104规则解析报文
            Packet pkt = frame.getAndAnalysePacket();

            // 初始化一个point对象，避免在循环中多次创建
            List<Point> points = new ArrayList<>();
            if (pkt.getPacketType() == Packet.PacketEnum.I) {
                List<Packet.AnalogSignals> analogSignals = pkt.getAnalogSignals();
                if (analogSignals.size() > 0) {
                    for (Packet.AnalogSignals analogSignal : analogSignals) {
                        int infoAdr = analogSignal.getInfoAdr();
                        Point p = new Point();
                        p.setDirection(direction);
                        p.setPointId(infoAdr);
                        p.setSubstationId(substation.getId());
                        // 过滤掉用户未配置的点位
                        if (grabberDao.countPointFilter(p) != 0) {
                            points.add(p);
                        }
                    }
                }
                List<Packet.DigitalSignals> digitalSignals = pkt.getDigitalSignals();
                if (digitalSignals.size() > 0) {
                    for (Packet.DigitalSignals digitalSignal : digitalSignals) {
                        int infoAdr = digitalSignal.getInfoAdr();
                        Point p = new Point();
                        p.setDirection(direction);
                        p.setPointId(infoAdr);
                        p.setSubstationId(substation.getId());
                        // 过滤掉用户未配置的点位
                        if (grabberDao.countPointFilter(p) != 0) {
                            points.add(p);
                        }
                    }
                }
            }

            if (points.isEmpty()) {
                return false;
            }

            // 插入报文表和点位信息表
            grabberDao.insertPacket(pkt, frame.getId());
            for (Point point : points) {
                int pointSettingId = grabberDao.selectPointSettingIdByPointAddress(point.getPointId(), point.getSubstationId());
                point.setId(pointSettingId);
                // 如果报文类型为I, 根据报文方向获取主站host
                if (pkt.getPacketType() == Packet.PacketEnum.I) {
                    for (Packet.AnalogSignals as : pkt.getAnalogSignals()) {
                        point.setPacketId(pkt.getId());
                        point.setPointValue(as.getVal());
                        point.setPointQuality(as.getQds());
                        grabberDao.insertPacketPointInfo(point);
                    }
                    for (Packet.DigitalSignals ds : pkt.getDigitalSignals()) {
                        point.setPacketId(pkt.getId());
                        point.setPointValue(ds.getSpi());
                        point.setPointQuality(0);
                        grabberDao.insertPacketPointInfo(point);
                    }
                }
            }
        } catch (PacketVerifyException ex) {
            log.error("packet verify error", ex);
            grabberDao.updateBytesFrameAnalysisCause(frame.getId(), ex.getMessage());
            return false;
        }
        return true;
    }
}
